package com.edu.exam.entity.system.storage;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;

/**
 * PDF文件实体类
 *
 * <p>PDF文件实体用于管理试卷PDF文件的信息和存储，支持PDF生成、
 * 文件管理、完整性验证等功能。是试卷存储与版本控制的重要组成部分。</p>
 *
 * <p>核心功能：
 * - PDF管理：管理PDF文件的存储路径、文件名等信息
 * - 文件跟踪：记录文件大小、生成时间、生成人等元数据
 * - 完整性验证：通过校验和确保文件完整性
 * - 版本关联：与试卷版本建立关联关系
 * - 文件状态：跟踪文件的当前状态和可用性</p>
 *
 * @author 系统生成
 * @version 2.0
 * @since 2025-11-09
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@EntityListeners(AuditingEntityListener.class)
public class PDFFile {

    /**
     * 主键ID
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    /**
     * 关联试卷ID
     *
     * <p>关联的试卷ID，对应exam_paper表的主键。
     * 用于建立试卷与PDF文件的关联关系。</p>
     */
    @Column(name = "paper_id", nullable = false)
    private Long paperId;

    /**
     * 关联版本ID
     *
     * <p>关联的版本ID，对应paper_version表的主键。
     * 指向生成PDF时所依据的试卷版本。</p>
     */
    @Column(name = "version_id")
    private Long versionId;

    /**
     * PDF文件存储路径
     *
     * <p>PDF文件的完整存储路径。
     * 包含文件目录和文件名的完整路径。</p>
     */
    @Column(name = "file_path", nullable = false, length = 500)
    private String filePath;

    /**
     * PDF文件名
     *
     * <p>PDF文件的文件名（不包含路径）。
     * 按照统一规则命名，便于管理。</p>
     */
    @Column(name = "file_name", nullable = false, length = 200)
    private String fileName;

    /**
     * 文件大小
     *
     * <p>PDF文件的大小，单位为字节。
     * 用于文件大小统计和存储空间管理。</p>
     */
    @Column(name = "file_size", nullable = false)
    private Long fileSize;

    /**
     * 文件校验和
     *
     * <p>文件的MD5或其他哈希校验和。
     * 用于验证文件完整性和防止篡改。</p>
     */
    @Column(name = "checksum", nullable = false, length = 100)
    private String checksum;

    /**
     * 生成时间
     *
     * <p>PDF文件的生成时间。
     * 记录文件是何时生成的。</p>
     */
    @Column(name = "generate_time", nullable = false)
    private LocalDateTime generateTime;

    /**
     * 生成人
     *
     * <p>PDF文件的生成人员。
     * 记录是谁生成了这个PDF文件。</p>
     */
    @Column(name = "generated_by", nullable = false, length = 50)
    private String generatedBy;

    /**
     * 是否为当前版本
     *
     * <p>标识是否为试卷的当前有效PDF文件。
     * true表示当前版本，false表示历史版本。</p>
     */
    @Column(name = "is_current", nullable = false)
    private Boolean isCurrent = false;

    /**
     * 文件状态
     *
     * <p>PDF文件的状态标识。
     * 支持的状态包括：GENERATING（生成中）、COMPLETED（完成）、FAILED（失败）、DELETED（已删除）。</p>
     */
    @Column(name = "file_status", nullable = false, length = 20)
    private String fileStatus = "COMPLETED";

    /**
     * 生成模板
     *
     * <p>生成PDF时使用的模板名称。
     * 记录使用的是哪个PDF模板。</p>
     */
    @Column(name = "template_name", length = 100)
    private String templateName;

    /**
     * 生成配置
     *
     * <p>PDF生成时的配置参数（JSON格式）。
     * 包含页面设置、字体设置等配置信息。</p>
     */
    @Column(name = "generation_config", columnDefinition = "TEXT")
    private String generationConfig;

    /**
     * 生成耗时
     *
     * <p>PDF生成所花费的时间，单位为毫秒。
     * 用于性能分析和优化。</p>
     */
    @Column(name = "generation_duration")
    private Long generationDuration;

    /**
     * 页面数量
     *
     * <p>PDF文件的页面数量。
     * 用于统计和分析。</p>
     */
    @Column(name = "page_count")
    private Integer pageCount;

    /**
     * 文件格式
     *
     * <p>PDF文件的具体格式版本。
     * 例如：PDF-1.4、PDF-1.7等。</p>
     */
    @Column(name = "file_format", length = 20)
    private String fileFormat;

    /**
     * 是否加密
     *
     * <p>标识PDF文件是否加密。
     * true表示加密，false表示未加密。</p>
     */
    @Column(name = "is_encrypted")
    private Boolean isEncrypted = false;

    /**
     * 下载次数
     *
     * <p>PDF文件的下载次数统计。
     * 用于使用情况分析。</p>
     */
    @Column(name = "download_count")
    private Long downloadCount = 0L;

    /**
     * 最后下载时间
     *
     * <p>最后一次下载PDF文件的时间。</p>
     */
    @Column(name = "last_download_time")
    private LocalDateTime lastDownloadTime;

    /**
     * 访问权限
     *
     * <p>PDF文件的访问权限设置。
     * 控制谁可以访问和下载这个PDF文件。</p>
     */
    @Column(name = "access_permission", length = 50)
    private String accessPermission;

    /**
     * 过期时间
     *
     * <p>PDF文件的过期时间。
     * 过期后文件可能被自动清理。</p>
     */
    @Column(name = "expiry_time")
    private LocalDateTime expiryTime;

    /**
     * 生成错误信息
     *
     * <p>PDF生成失败时的错误信息。
     * 用于问题诊断和解决。</p>
     */
    @Column(name = "generation_error", columnDefinition = "TEXT")
    private String generationError;

    /**
     * 元数据
     *
     * <p>PDF文件的元数据信息（JSON格式）。
     * 包含标题、作者、创建时间等PDF元数据。</p>
     */
    @Column(name = "file_metadata", columnDefinition = "TEXT")
    private String fileMetadata;

    /**
     * 备份路径
     *
     * <p>PDF文件的备份存储路径。
     * 用于数据恢复和灾难备份。</p>
     */
    @Column(name = "backup_path", length = 500)
    private String backupPath;

    /**
     * 是否删除
     *
     * <p>软删除标记，标识记录是否已删除。
     * true表示已删除，false表示未删除。</p>
     */
    @Column(name = "is_deleted", nullable = false)
    private Boolean isDeleted = false;

    // ===== 审计字段 =====

    /**
     * 创建时间
     */
    @CreatedDate
    @Column(name = "created_time", nullable = false, updatable = false)
    private LocalDateTime createdTime;

    /**
     * 更新时间
     */
    @LastModifiedDate
    @Column(name = "updated_time", nullable = false)
    private LocalDateTime updatedTime;

    // ===== 常量定义 =====

    // 文件状态常量
    /** 文件状态 - 生成中 */
    public static final String STATUS_GENERATING = "GENERATING";

    /** 文件状态 - 完成 */
    public static final String STATUS_COMPLETED = "COMPLETED";

    /** 文件状态 - 失败 */
    public static final String STATUS_FAILED = "FAILED";

    /** 文件状态 - 已删除 */
    public static final String STATUS_DELETED = "DELETED";

    /** 文件状态 - 过期 */
    public static final String STATUS_EXPIRED = "EXPIRED";

    // 访问权限常量
    /** 访问权限 - 公开 */
    public static final String PERMISSION_PUBLIC = "PUBLIC";

    /** 访问权限 - 私有 */
    public static final String PERMISSION_PRIVATE = "PRIVATE";

    /** 访问权限 - 受限 */
    public static final String PERMISSION_RESTRICTED = "RESTRICTED";
}